import * as vscode from 'vscode';
import axios from 'axios';

const DEEPSEEK_API_URL = 'https://api.deepseek.com/v1/chat/completions';
const DEEPSEEK_API_URL_BETA = 'https://api.deepseek.com/beta'

export function activate(context: vscode.ExtensionContext) {
    // 注册代码补全功能
    const inlineCompletionProvider = new CodeInlineCompletionProvider();
    context.subscriptions.push(
        vscode.languages.registerInlineCompletionItemProvider(
            { scheme: 'file' },
            inlineCompletionProvider
        )
    );

    // 注册可交互命令：解释命令、优化命令
    const codeLensProvider = new CodeLensProvider();
    context.subscriptions.push(
        vscode.languages.registerCodeLensProvider(
            { scheme: 'file' },
            codeLensProvider
        )
    );

    // 注册代码解释命令
    context.subscriptions.push(
        vscode.commands.registerCommand('deepseek.extension.explainCode', 
			async (functionName: string, 
                document: vscode.TextDocument) => {
            console.log("触发解释代码功能。");

            // 请求解释代码并提示用户
            vscode.window.withProgress(
                {
                    location: vscode.ProgressLocation.Notification,
                    title: '正在请求解释代码...',
                    cancellable: false
                },
                async (progress, token) => {
                    try {
                        // 获取函数的开始和结束位置
                        const functionRange = getFunctionRange(
                            document, 
                            functionName);
                        console.log(functionRange)

                        if (functionRange) {
                            // 获取当前函数的代码片段
                            const functionCode = document.getText(functionRange);
                            const prompt = `请解释以下函数代码：\n${functionCode}`;
                            console.log(prompt);

                            // 请求 AI 解释代码
                            const explanation = await getAIResponse(prompt);
                            console.log(explanation);

                            // 显示 AI 的解释结果
                            showAIResponse(explanation, '解释代码');
                        } else {
                            vscode.window.showErrorMessage('无法找到当前函数的代码范围。');
                        }

                        return; // 完成任务
                    } catch (error) {
                        // 错误处理
                        vscode.window.showErrorMessage('获取代码解释失败，请稍后再试。');
                        console.error("解释代码时出现错误: ", error);
                        return; // 任务完成但失败
                    }
                }
            );
        })
    );


    // 注册代码优化命令
    context.subscriptions.push(
        vscode.commands.registerCommand('deepseek.extension.optimizeCode', 
			async (functionName: string, document: vscode.TextDocument) => {
            console.log("触发优化代码功能。");

            // 提示用户优化代码
            vscode.window.withProgress(
                {
                    location: vscode.ProgressLocation.Notification,
                    title: '正在请求优化代码...',
                    cancellable: false
                },
                async (progress, token) => {
                    try {
                        // 获取函数的开始和结束位置
                        const functionRange = getFunctionRange(
                            document, 
                            functionName);

                        if (functionRange) {
                            // 获取当前函数的代码片段
                            const functionCode = document.getText(functionRange);
                            const prompt = `请优化以下函数代码：\n${functionCode}`;

                            console.log(prompt);

                            // 请求 AI 优化代码
                            const optimizedCode  = await getAIResponse(prompt);

                            // 显示 AI 的解释结果
                            showAIResponse(optimizedCode , '优化代码');
                        } else {
                            vscode.window.showErrorMessage('无法找到当前函数的代码范围。');
                        }

                        return; // 完成任务
                    } catch (error) {
                        // 错误处理
                        vscode.window.showErrorMessage('优化代码失败，请稍后再试。');
                        console.error("优化代码时出现错误: ", error);
                        return; // 任务完成但失败
                    }
                }
            );
        })
    );

}

// 获取当前函数的代码范围
/* function getFunctionRange(document: vscode.TextDocument, 
    position: vscode.Position, 
    functionName: string): vscode.Range | null {
    const text = document.getText();
    const functionRegex = new RegExp(
        `function\\s+${functionName}\\s*\\([^)]*\\)\\s*{[^}]*}`, 'g');
    const match = 
        functionRegex.exec(text.substring(0, document.offsetAt(position)));
    
    if (match) {
        const startPos = document.positionAt(text.indexOf(match[0]));
        const endPos = 
            document.positionAt(text.indexOf(match[0]) + match[0].length);
        return new vscode.Range(startPos, endPos);
    }

    return null;
} */

function getFunctionRange(
    document: vscode.TextDocument,
    functionName: string
): vscode.Range | null {
    const text = document.getText();
    
    // 转义函数名中的特殊字符
    const escapedName = functionName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    
    // 匹配函数声明头 (function name(...) { )
    const headerRegex = new RegExp(
        `\\bfunction\\s+${escapedName}\\s*\\([^)]*\\)\\s*{`,
        'g'
    );

    // 存储候选的完整匹配信息
    const candidates: {
        headerStart: number;  // 函数头起始位置
        headerLength: number; // 函数头长度（包含 { ）
        bodyStart: number;    // 函数体 { 的位置
    }[] = [];

    // 阶段1：记录所有候选信息
    let match: RegExpExecArray | null;
    while ((match = headerRegex.exec(text)) !== null) {
        if (match.index === undefined) continue;

        candidates.push({
            headerStart: match.index,
            headerLength: match[0].length,
            bodyStart: match.index + match[0].length - 1 // 定位到 { 的位置
        });
    }

    // 阶段2：验证每个候选
    for (const candidate of candidates) {
        let depth = 1;
        let currentPos = candidate.bodyStart + 1; // 从 { 的下一个字符开始

        while (currentPos < text.length) {
            // 处理字符串字面量（增强版）
            const char = text[currentPos];
            if (['"', "'", '`'].includes(char)) {
                const closerIndex = findStringEnd(text, currentPos, char);
                if (closerIndex === -1) break;
                currentPos = closerIndex + 1;
                continue;
            }

            // 处理注释（增强版）
            if (char === '/' && currentPos + 1 < text.length) {
                const nextChar = text[currentPos + 1];
                if (nextChar === '/') {
                    const lineEnd = text.indexOf('\n', currentPos);
                    currentPos = lineEnd === -1 ? text.length : lineEnd + 1;
                    continue;
                } else if (nextChar === '*') {
                    const commentEnd = text.indexOf('*/', currentPos);
                    if (commentEnd === -1) break;
                    currentPos = commentEnd + 2;
                    continue;
                }
            }

            // 更新深度
            if (char === '{') depth++;
            if (char === '}') depth--;

            // 找到闭合点
            if (depth === 0) {
                const startOffset = candidate.headerStart;
                const endOffset = currentPos + 1; // 包含闭合 }
                
                return new vscode.Range(
                    document.positionAt(startOffset),
                    document.positionAt(endOffset)
                );
            }

            currentPos++;
        }
    }

    return null;
}

// 辅助函数：查找字符串结束位置
function findStringEnd(text: string, start: number, quote: string): number {
    let pos = start + 1;
    let escape = false;

    while (pos < text.length) {
        const char = text[pos];
        
        if (escape) {
            escape = false;
        } else {
            if (char === '\\') escape = true;
            if (char === quote) return pos;
        }
        
        pos++;
    }
    return -1;
}

// Inline 提供者
class CodeInlineCompletionProvider 
    implements vscode.InlineCompletionItemProvider {
    async provideInlineCompletionItems(
        document: vscode.TextDocument,
        position: vscode.Position
    ): Promise<vscode.InlineCompletionItem[]> {
        console.log("触发代码补全功能");

        // 获取当前源文件全部内容
        const sourceCode = document.getText();

        const sourceCodeTrim = sourceCode.trim();

        // 当上下文为空
        if (sourceCodeTrim == "") {
            return [];
        }

        console.log(sourceCodeTrim);

        try {
            // 获取 AI 响应
            //const response = await getAIResponseByPrefix(sourceCodeTrim);
            const prompt = `请补全以下代码，
                除代码及注释外外不要添加任何其他信息，禁止给出当前已有代码，
                仅返回补全部分的代码，
                最多继续完成一个函数，
                如果使用注释理解程序员意图时，应优先使用离待补全代码最近的注释：
                ${sourceCodeTrim}`;
            const response = await getAIResponse(prompt);

            // 清理返回的代码（去除语言标记等）
            let cleanResponse = 
                response.replace(/```[a-zA-Z]*\n|\n```/g, '').trim();

            console.log("代码补全返回：");
            console.log(cleanResponse);

            // 创建内联补全项
            const inlineCompletionItem = 
                new vscode.InlineCompletionItem(cleanResponse);

            // 设置补全的显示方式
            inlineCompletionItem.range = new vscode.Range(
                position.with(undefined, 0),
                position
            );
            
            inlineCompletionItem.command = {
                command: 'editor.action.triggerSuggest',
                title: '触发代码补全',
            };

            return [inlineCompletionItem];
        } catch (error) {
            vscode.window.showErrorMessage('代码补全请求失败,' + error);
            return [];
        }
    }
}


// CodeLens 提供者
class CodeLensProvider implements vscode.CodeLensProvider {
    provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] {
        // 在每个函数或者类上添加 CodeLens 按钮
        const codeLenses: vscode.CodeLens[] = [];

        //const regex = /^(?!.*\/\/)(?!.*\/\*).*\bfunction\s+([a-zA-Z0-9_]+)\s*\(/gm;
        const regex = /^(?!(?:\s*\/\/|\s*\/\*|.*['"`])).*?\bfunction\s+([a-zA-Z_$][\w$]*)\s*\(/gm;
        let match: RegExpExecArray | null;

        // 查找文档中的函数定义
        while ((match = regex.exec(document.getText())) !== null) {
            const functionName = match[1];
            const startPos = document.positionAt(match.index);
            const endPos = document.positionAt(match.index + match[0].length);
            const range = new vscode.Range(startPos, endPos);

            // 创建解释代码和优化代码的 CodeLens
            codeLenses.push(new vscode.CodeLens(range, {
                title: `解释代码`,
                command: 'deepseek.extension.explainCode',
                arguments: [functionName, document]
            }));

            codeLenses.push(new vscode.CodeLens(range, {
                title: `优化代码`,
                command: 'deepseek.extension.optimizeCode',
                arguments: [functionName, document]
            }));
        }

        return codeLenses;
    }

    resolveCodeLens(codeLens: vscode.CodeLens): vscode.CodeLens {
        // 解析并返回 CodeLens
        return codeLens;
    }
}

async function getAIResponse(prompt: string): Promise<string> {
    const config = vscode.workspace.getConfiguration('deepseek');
    const apiKey = config.get<string>('apiKey');

    if (!apiKey) {
        vscode.window.showErrorMessage('请先配置DeepSeek API密钥');
        return '';
    }

    const response = await axios.post(DEEPSEEK_API_URL, {
        model: "deepseek-chat",
        messages: [
            { role: "user", content: prompt }
        ],
        temperature: 0.7,
        max_tokens: 1000
    }, {
        headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
        }
    });

    return response.data.choices[0].message.content.trim();
}

async function getAIResponseByPrefix (prompt: string): Promise<string> {
    const config = vscode.workspace.getConfiguration('deepseek');
    const apiKey = config.get<string>('apiKey');

    if (!apiKey) {
        vscode.window.showErrorMessage('请先配置DeepSeek API密钥');
        return '';
    }

    prompt = "```JavaScript\n" + prompt
    let messageList = [
        {"role": "user", "content": "请根据已完成部分代码，继续补全剩余代码。" },
        {"role": "assistant", "content": prompt, "prefix": "True"}
    ]
    //console.log(messageList)

    const response = await axios.post(DEEPSEEK_API_URL_BETA, {
        model: "deepseek-chat",
        messages: messageList,
        stop: "```",
        temperature: 0.7,
        max_tokens: 1000
    }, {
        headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
        }
    });

    return response.data.choices[0].message.content.trim();
}

function showAIResponse(content: string, title: string) {
    const panel = vscode.window.createWebviewPanel(
        'deepseekResponse',
        `DeepSeek - ${title}`,
        vscode.ViewColumn.Beside,
        {
            enableScripts: true, // 启用脚本
            localResourceRoots: [] // 可选：指定 WebView 的本地资源目录
        }
    );

    // 使用 Markdown 格式展示内容
    panel.webview.html = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>${title}</title>
        <style>
            body {
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                padding: 10px;
                line-height: 1.6;
            }
            code {
                display: block;
                background-color: #f5f5f5;
                color: black; /* 设置代码块文字颜色为黑色 */
                padding: 10px;
                border-radius: 4px;
                overflow-x: auto;
            }
            pre {
                background-color: #f5f5f5; /* 背景色 */
                color: black; /* 设置代码块文字颜色为黑色 */
                padding: 10px;
                border-radius: 4px;
                overflow-x: auto;
                font-size: 14px;
                line-height: 1.5;
            }
        </style>
    </head>
    <body>
        <h2>${title}</h2>
        <div>
            ${markdownToHtml(content)}
        </div>
    </body>
    </html>`;

    // 将内容转为 Markdown 格式（支持代码块）
    function markdownToHtml(content: string): string {
        const codeBlocks: string[] = [];
        
        // 第一阶段：提取代码块
        let processed = content.replace(
            /```([\w-]+)?\n([\s\S]*?)\n```/g,
            (_, lang, code) => {
                codeBlocks.push(code);
                return `\x1Bcode${codeBlocks.length - 1}\x1B`;
            }
        );
    
        // 第二阶段：常规转换
        processed = processed
            .replace(/^(#{1,6})\s+(.+)$/gm, (_, hashes, text) => `<h${hashes.length}>${text.trim()}</h${hashes.length}>`)
            .replace(/^(\s*)[*\-+]\s+([^\n]*)/gm, '<ul><li>$2</li></ul>')
            .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
            .replace(/\*(.*?)\*/g, '<em>$1</em>')
            .replace(/\n{2,}/g, '\n</p>\n<p>')
            .replace(/^([\s\S]*?)$/m, '<p>$1</p>')
            .replace(/\n/g, '<br/>');
    
        // 第三阶段：恢复代码块
        let html = processed.replace(
            /\x1Bcode(\d+)\x1B/g,
            (_, index) => `<pre><code class="language-${content.match(/```([\w-]+)?\n/)?.[1] || 'none'}">${escapeHtml(codeBlocks[Number(index)])}</code></pre>`
        );
    
        // 新增第四阶段：清理冗余换行
        html = html.replace(
            /(<\/?(h[1-6]|ul|li|pre|code|p)(?:\s+[^>]*?)?>)\s*<br\/?>/gi,
            '$1' // 删除紧跟在块级标签后的换行标记
        );
    
        return html;
    }
    
    
    // 增强的HTML实体转义
    function escapeHtml(text: string): string {
        return text.replace(/[&<>"']/g, (char) => ({
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#39;'
        }[char]!));
    }
}


export function deactivate() { }
